package com.efast.cafe.commponent.statemach.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.efast.cafe.commponent.crud.service.ICrudV2Service;
import com.efast.cafe.commponent.crud.service.impl.CrudSqlGenerateUtils;
import com.efast.cafe.commponent.statemach.bean.*;
import com.efast.cafe.commponent.statemach.dao.PortalStateMachTaskDao;
import com.efast.cafe.commponent.statemach.service.*;
import com.efast.cafe.framework.enums.ResultStatus;
import com.efast.cafe.framework.exception.ServiceException;
import com.efast.cafe.framework.jdbc.JdbcDao;
import com.efast.cafe.framework.redis.locker.LockerFactory;
import com.efast.cafe.framework.redis.locker.RedissonDistributedLocker;
import com.efast.cafe.framework.util.SpringWebUtils;
import com.efast.cafe.portal.bean.api.PortalApiViewBean;
import com.efast.cafe.portal.bean.common.EntityFieldInfoBean;
import com.efast.cafe.portal.bean.common.EntityInfoBean;
import com.efast.cafe.portal.bean.statemach.PortalStateMachField;
import com.efast.cafe.portal.bean.statemach.PortalStateMachHandleBean;
import com.efast.cafe.portal.bean.statemach.PortalStateMachStateBean;
import com.efast.cafe.portal.entity.common.PortalAttachmentForm;
import com.efast.cafe.portal.entity.company.PortalCompanyRole;
import com.efast.cafe.portal.remote.api.PortalApiViewService;
import com.efast.cafe.portal.remote.common.EntityInfoQueryService;
import com.efast.cafe.portal.remote.common.PortalAttachmentService;
import com.efast.cafe.portal.remote.company.PortalCompanyUserService;
import com.efast.cafe.portal.remote.statemach.PortalStatemachFieldAuthService;
import com.efast.cafe.util.StringUtil;

import org.apache.commons.lang.StringUtils;
import org.redisson.api.RLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
@Transactional
public class PortalStateMachTaskServiceImpl implements IPortalStateMachTaskService {
    @Autowired
    private IPortalStateMachService portalStateMachService;

    @Autowired
    private EntityInfoQueryService queryService;

    @Autowired
    private JdbcDao jdbcDao;

    @Autowired
    private CrudSqlGenerateUtils crudSqlGenerateUtils;

    @Autowired
    private IPortalStateMachResourceService stateMachResourceService;

    @Autowired
    private IPortalStateMachResourceTaskService stateMachResourceTaskService;

    @Autowired
    private PortalStateMachTaskDao taskDao;

    @Autowired
    private ICrudV2Service crudV2Service;

    @Autowired
    private IStateMachService stateMachService;

    @Autowired
    private IPortalStateMachTaskHistoryService portalStateMachTaskHistoryService;

    @Autowired
    private PortalAttachmentService portalAttachmentService;

    @Autowired
    private PortalCompanyUserService portalCompanyUserService;
    @Autowired
    private PortalStatemachFieldAuthService portalStatemachFieldAuthService;
    @Autowired
    private PortalApiViewService portalApiViewService;

    @Override
    public void begin(TaskParamBean taskParam,Map<String, JSONObject> extFormDataJson) {
        // PortalStateMachConfBean portalStateMachBean =
        // portalStateMachService.getPortalStateMachByConfId(taskParam.getConfId());
        stateBegin(taskParam.getConfId(), taskParam.getParajson(),extFormDataJson);
       
    }

    @Override
    public void operation(TaskParamBean taskParam,Map<String, JSONObject> extFormDataJson) {
        
        stateOperation(taskParam.getConfId(), taskParam.getTaskId(), taskParam.getParajson(),extFormDataJson);
    }

    @Override
    public void stateBegin(Long confId, String t,Map<String, JSONObject> extFormDataJson){
        // 存储当前状态对象
        PortalStateMachStateBean thisStateBean = null;
        // json反序列化
        StateMachTaskBean smt = JSON.parseObject(t, StateMachTaskBean.class);
        smt.setCompanyCode(SpringWebUtils.getRequestCompany());
        smt.setCreateUser(SpringWebUtils.getRequestUser());
        smt.setConfId(confId);
        // 获取初始化状态
        thisStateBean = portalStateMachService.getInitState(confId);
        smt.setStateId(thisStateBean.getId());
        // 获取条件
        List<PortalStateMachHandleBean> thisHandle = thisStateBean.getHeadle();
        PortalStateMachHandleBean execHandle = portalStateMachService.getExecHandle(thisHandle, t);
        //校验操作权限
        checkPermissionHandle(execHandle);
        
        if (execHandle.getChangeStateId() != null) {
            smt.setStateId(execHandle.getChangeStateId());
        }
        if (thisStateBean.getUpdateField() != null && !thisStateBean.getUpdateField().isEmpty()) {
            smt = UpdateTaskByResource(smt, t, thisStateBean.getUpdateField());
        }
        // 创建人
        smt.setCreateUser(SpringWebUtils.getRequestUser());

        // 创建task
        Long Id = this.init(smt);
        // 添加历史记录
        if (execHandle.getChangeStateId() != null) {
            insertTaskHistory(Id, thisStateBean.getId(), execHandle.getId(), confId, execHandle.getChangeStateId(), smt.getRemark());
        }
        // 当前状态是否需要添加资源
        AddResource(thisStateBean, t, Id);

        // 当前状态下是否有扩展表单
        AddExtForm(thisStateBean, t, Id, true, execHandle.getChangeStateId(), confId,extFormDataJson);

    }

    @Override
    public void stateOperation(Long confId, Long Id, String t,Map<String, JSONObject> extFormDataJson){
        // 存储当前状态对象
        PortalStateMachStateBean thisStateBean = null;
        // 获取执行操作
        PortalStateMachHandleBean execHandle = null;
        // json反序列化
        StateMachTaskBean smt = JSON.parseObject(t, StateMachTaskBean.class);

        // 获取当前状态
        List<PortalStateMachHandleBean> thisHandle = null;
        Long thisState = portalStateMachService.getState(Id);
        thisStateBean = portalStateMachService.getCurrentState(confId, thisState);
           
        // 获取操作
        thisHandle = thisStateBean.getHeadle();
        execHandle = portalStateMachService.getExecHandle(thisHandle, t);
        // 执行状态变更
        if (execHandle.getChangeStateId() != null) {
        	//校验操作权限
        	checkPermissionHandle(execHandle);
        	 if (thisStateBean.getUpdateField() != null && !thisStateBean.getUpdateField().isEmpty()) {
                 smt = UpdateTaskByResource(smt, t, thisStateBean.getUpdateField());
             }
             // 判断当前状态是否添加资源
             AddResource(thisStateBean, t, Id);
             // 当前状 态下是否有扩展表单
             AddExtForm(thisStateBean, t, Id, false, execHandle.getChangeStateId(), confId,extFormDataJson);
             // 修改人
             smt.setLastUpdateUser(SpringWebUtils.getRequestUser());
        	
            if (execHandle.getChangeStateId() > 0) {
                smt.setStateId(execHandle.getChangeStateId());
            }
            smt.setId(Id);
            // 更新数据
            taskDao.updateStatePart(smt);
            // 添加历史记录
            insertTaskHistory(Id, thisStateBean.getId(), execHandle.getId(), confId,
                    execHandle.getChangeStateId() > 0 ? execHandle.getChangeStateId() : thisStateBean.getId(),
                    smt.getRemark());
            
            // 锁定资源
            lockResource(execHandle.getChangeResource(), Id);
        }else{
        	throw new ServiceException(ResultStatus.DATA_VERSION_ERROR.getCode(), 
        			ResultStatus.DATA_VERSION_ERROR.getMessage());
        }
           
    }

	
	    
	private void checkPermissionHandle(PortalStateMachHandleBean execHandle) {
		List<PortalCompanyRole> userHasRoleList = portalCompanyUserService
		        .api_queryUserHasRoleList(SpringWebUtils.getRequestUser(), SpringWebUtils.getRequestCompany());
		if(!checkHandleAuthority(userHasRoleList, execHandle.getExeRole(), execHandle.getExeUser())){
			//没有权限操作该handle
			throw new ServiceException(ResultStatus.PERMISSION_ERRIR.getCode(),
					ResultStatus.PERMISSION_ERRIR.getMessage());
		}
	}

    /**
     * 任务添加资源
     *
     * @param thisStateBean
     * @param t
     * @param Id
     */
    private void AddResource(PortalStateMachStateBean thisStateBean, String t, Long Id) {
        // 判断当前状态是否添加资源
        if (thisStateBean != null) {
            if (thisStateBean.getResource() != null) {
                // 两种情况可能配置的是(1)类别(2)特定资源
                JSONObject resconf = JSON.parseObject(thisStateBean.getResource());
                if (resconf.getString("resType").length() > 0) {
                    String[] ress = resconf.getString("resTypeItems").split(";");
                    for (String res : ress) {
                        StateMachResourceTask insertSMRT = new StateMachResourceTask();
                        insertSMRT.setRelType(1);
                        insertSMRT.setTaskId(Id);
                        insertSMRT.setRelObjectName(res.split(":")[0]);
                        insertSMRT.setRelId(new Long(res.split(":")[1]));
                        stateMachResourceTaskService.insertResourceTask(insertSMRT);
                    }

                } else {
                    String[] resourceKeys = resconf.getString("resName").split(",");
                    for (String resourceKey : resourceKeys) {
                        if (JSON.parseObject(t).containsKey(resourceKey)
                                && !JSON.parseObject(t).getString(resourceKey).isEmpty()) {
                            // 创建关系
                            StateMachResourceTask insertSMRT = new StateMachResourceTask();
                            insertSMRT.setRelType(1);
                            insertSMRT.setTaskId(Id);
                            insertSMRT.setRelObjectName(resourceKey);
                            insertSMRT.setRelId(new Long(JSON.parseObject(t).getString(resourceKey)));
                            stateMachResourceTaskService.insertResourceTask(insertSMRT);
                        }
                    }
                }

            }
        }
    }

    /**
     * 任务添加扩展表单
     *
     * @param thisStateBean
     * @param t
     * @param Id
     * @throws ScriptException
     */

    private void AddExtForm(PortalStateMachStateBean thisStateBean, String t, Long Id, boolean isInsert,
                            Long changeStateId, Long confId,Map<String, JSONObject> extFormDataJson){
        if (thisStateBean != null) {
            if (StringUtil.isNotBlank(thisStateBean.getExtForm())) {
                EntityInfoBean en = queryService.queryEntityInfo(thisStateBean.getExtForm());
                grenateExtForm(thisStateBean, t, Id, isInsert, changeStateId, confId, en,extFormDataJson);
            }else if(StringUtil.isNotBlank(thisStateBean.getViewCode())){
            	PortalApiViewBean viewObj = portalApiViewService.selectViewByCode(thisStateBean.getViewCode());
            	if(null!=viewObj){
            		String entitiesDetail = viewObj.getEntitiesDetail();
            		JSONArray jr = JSONArray.parseArray(entitiesDetail);
            		for(int i=0; i<jr.size();i++){
            			JSONObject jo = jr.getJSONObject(i);
            			String extForm = jo.getString("entityKey");
            			if(StringUtil.isNotBlank(extForm)){
                			EntityInfoBean en = queryService.queryEntityInfo(extForm);
                			grenateExtForm(thisStateBean, t, Id, isInsert, changeStateId, confId, en,extFormDataJson);
                		}
            		}
            		
            	}
            }
        }
    }

	
	   
	    
	public void grenateExtForm(PortalStateMachStateBean thisStateBean, String t, Long Id, boolean isInsert,
			Long changeStateId, Long confId, EntityInfoBean en,Map<String, JSONObject> extFormDataJson){
		if (null == en) {
		    throw new ServiceException("StateMachTask.error.extFormEntity.definition",
		            thisStateBean.getExtForm());
		}
		
		
		JSONObject extData = JSON.parseObject(t).getJSONObject("extFormData")
		        .getJSONObject(en.getEntityName());
		// 获取参数
		Map<String, Object> param = new HashMap<String, Object>();
		if (extData != null && !extData.isEmpty()) {
		    List<PortalAttachmentForm> list = new ArrayList<PortalAttachmentForm>();
		    for (int k = 0; k < en.getAttrs().size(); k++) {
		        // 先处理附件属性，再处理其他的
		        if (en.getAttrs().get(k).getField().getFieldType() == 6
		                && extData.containsKey(en.getAttrs().get(k).getField().getFieldName())) {
		            if (extData.containsKey("generateFormId")) {
		                String[] grops = StringUtils
		                        .isBlank(
		                                extData.getString(en.getAttrs().get(k).getField().getFieldName()))
		                        ? null
		                        : extData
		                        .getString(
		                                en.getAttrs().get(k).getField().getFieldName())
		                        .replace("[", "").replace("]", "").split(",");
		                if (grops != null && grops.length > 0) {
		                    for (String grop : grops) {
		                        PortalAttachmentForm af = new PortalAttachmentForm();
		                        af.setFormId(extData.getString("generateFormId"));
		                        af.setGroupId(en.getAttrs().get(k).getField().getFieldName());
		                        af.setAttachmentId(Integer.parseInt(grop));
		                        af.setCompanyCode(SpringWebUtils.getRequestCompany());
		                        af.setCreateUser(SpringWebUtils.getRequestUser());
		                        list.add(af);
		                    }
		                }

		            }
		        } else if (extData.containsKey(en.getAttrs().get(k).getField().getFieldName())) {
		            if (en.getAttrs().get(k).getField().getFieldType() == 4) {
		                param.put(en.getAttrs().get(k).getField().getFieldName(),
		                        extData.getString(en.getAttrs().get(k).getField().getFieldName()) == null ? null
		                                : extData.getString(en.getAttrs().get(k).getField().getFieldName()));
		            } else {
		                param.put(en.getAttrs().get(k).getField().getFieldName(),
		                        extData.getString(en.getAttrs().get(k).getField().getFieldName()) == null ? ""
		                                : extData.getString(en.getAttrs().get(k).getField().getFieldName()));
		            }
		        }
		    }
		    // 添加附件
		    portalAttachmentService.saveAttachmentForm(extData.getString("generateFormId"), list);
		    if (changeStateId != null) {
		        // 根据当前状态的updateField更新扩展表单
		        param = updateExtDataForState(param, changeStateId, t, confId,en.getTableName());
		    }
		    
		    Map<String, List<String>> map = portalStatemachFieldAuthService.
            		queryFieldAuthBy(confId.intValue(), thisStateBean.getId().intValue(), en.getTableName());
			List<String> non_editables =  map.get("non_editables"); //不可编辑字段
			List<String> required = map.get("required"); //需要校验的字段
			List<EntityFieldInfoBean> entityFields = 
		    		   validationParams(param, non_editables, required, en.getAttrs());
		    if (isInsert) {
		        List<Object> params = new ArrayList<>();
		        
		        String sql = crudSqlGenerateUtils.buildInsertSql(en.getTableName(), param, entityFields,
		                en.getExtAttrs(), false, params);
		        Integer id = jdbcDao.insertBySQLAndGetKey(sql, params);
		        
		        extData.put("id", id);
		        extFormDataJson.put(en.getEntityName(), extData);

		        // 创建关系
		        StateMachResourceTask insertSMRT = new StateMachResourceTask();
		        insertSMRT.setRelType(2);
		        insertSMRT.setTaskId(Id);
		        insertSMRT.setRelObjectName(en.getTableName());
		        insertSMRT.setRelId(new Long(id));
		        stateMachResourceTaskService.insertResourceTask(insertSMRT);
		    } else {
		        // 判断当前关系是否存在
		        StateMachResourceTask smrt = stateMachResourceTaskService.getResourceTaskByIdAndName(Id,
		                en.getTableName());
		        // 不存在则创建，否则更新
		        if (smrt != null) {// 更新
		            param.put("id", smrt.getRelId());
		            List<Object> params = new ArrayList<>();
		            String sql = crudSqlGenerateUtils.buildUpdateSql(en.getTableName(), param, entityFields,
		                    en.getExtAttrs(), false, params);
		            jdbcDao.executeBySQL(sql, params);
		            
		            extFormDataJson.put(en.getEntityName(), extData);
		            
		        } else {// 插入
		            List<Object> params = new ArrayList<>();
		            String sql = crudSqlGenerateUtils.buildInsertSql(en.getTableName(), param, entityFields,
		                    en.getExtAttrs(), false, params);
		            Integer id = jdbcDao.insertBySQLAndGetKey(sql, params);
		            
		            extData.put("id", id);
			        extFormDataJson.put(en.getEntityName(), extData);

		            // 创建关系
		            StateMachResourceTask insertSMRT = new StateMachResourceTask();
		            insertSMRT.setRelType(2);
		            insertSMRT.setTaskId(Id);
		            insertSMRT.setRelObjectName(en.getTableName());
		            insertSMRT.setRelId(new Long(id));
		            stateMachResourceTaskService.insertResourceTask(insertSMRT);
		        }
		    }
		}
	}

		
		 
		/**
		 * 
		    * @Title: validationParams
		    * @Description: 校验节点中保存实体字段的权限
		    * @param @param param 实际数据的参数
		    * @param @param non_editables 不可编辑的字段
		    * @param @param required 必填的字段
		    * @param @param entityFields 实体的字段集合
		    * @param @return    参数
		    * @return List<EntityFieldInfoBean>    返回可操作的字段集合
		    * @throws 字段必填
		 */
		private List<EntityFieldInfoBean> validationParams(Map<String, Object> param, List<String> non_editables, List<String> required,
				List<EntityFieldInfoBean> entityFields) {
			List<EntityFieldInfoBean> newEntityFields = new ArrayList<>();
		       for(EntityFieldInfoBean field : entityFields){
		    	   if(!non_editables.contains(field.getField().getFieldName())){
		    		   newEntityFields.add(field);
		    	   }
		    	   if(required.contains(field.getField().getFieldName()) && 
		    			   param.containsKey(field.getField().getFieldName())){
		    		   if(param.get(field.getField().getFieldName())==null || 
		    				   StringUtil.isNullOrBlank(param.get(field.getField().getFieldName()).toString())){
		    			   throw new ServiceException(ResultStatus.PARAM_REQUIRED_ERROR.getCode(),
		    					   ResultStatus.PARAM_REQUIRED_ERROR.getMessage(field.getField().getFieldName()),
		    					   new String[]{field.getField().getFieldName()});
		    		   }
		    	   }
		       }
		       return newEntityFields;
		}

    /**
     * 插入Task
     *
     * @param stateMachTask
     * @return
     */
    private Long init(StateMachTaskBean stateMachTask) {
        // TODO Auto-generated method stub
        // 生存单号
        SimpleDateFormat fmt = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        stateMachTask.setTaskCode(fmt.format(new java.util.Date()));
        taskDao.insertState(stateMachTask);
        return stateMachTask.getId();
    }

    private StateMachTaskBean UpdateTaskByResource(StateMachTaskBean smt, String t, String exps){
        // 解析更新配置数组
        JSONArray jarr = JSONArray.parseArray(exps);
        for (Iterator<Object> iterator = jarr.iterator(); iterator.hasNext(); ) {
            JSONObject exp = (JSONObject) iterator.next();
            // 如果配置不包含table键则更新task，包含table的要去更新扩展表单
            if (!exp.containsKey("table")) {
                String updatefile = "";
                // 更新字段
                String updateFieldName = exp.getString("key");
                Object updateFieldValue = null;
                // 解析更新内容
                if (exp.getString("value") == null || exp.getString("value").isEmpty()) {// 解析js
                    // 创建js处理对象
                    ScriptEngineManager manager = new ScriptEngineManager();
                    ScriptEngine engine = manager.getEngineByName("JavaScript");
                    // 获取js
                    JSONObject js = exp.getJSONObject("js");
                    // 获取参数
                    JSONArray paras = JSONArray.parseArray(js.getString("para"));
                    for (Iterator<Object> parasiterator = paras.iterator(); parasiterator.hasNext(); ) {
                        JSONObject para = (JSONObject) parasiterator.next();
                        JSONObject valjson = JSON.parseObject(t);
                        // 处理para参数结构
                        String[] strparas = (para.getString("value")).split("\\.");
                        int i = 0;
                        for (String val : strparas) {
                            i++;
                            if (i < strparas.length) {
                                valjson = valjson.getJSONObject(val);
                            }
                        }
                        engine.put(para.getString("key"), valjson.getString(strparas[strparas.length - 1]));
                    }
                    // String a = "{\"js\":\"IF(isdriver==1)\'taskUser\'
                    // ELSE\'fms_driver.username\'\"}";
                    // JSONObject aj = JSON.parseObject(a);
                    // System.out.printf(js.getString("js"));
                    try {
						updatefile = (String) engine.eval(js.getString("js"));
					} catch (ScriptException e) {
						throw new ServiceException(ResultStatus.SYS_ERROR.getCode(),"执行javascript脚本失败");
					}
                    // updatefile = (String)
                    // engine.eval("if(isdriver==1){'taskUser'}
                    // else{'fms_driver.username'}");
                } else {// 解析value
                    updatefile = exp.getString("value");
                }
                if (updatefile.contains(".")) {// 如果value包含'.'表示源资源内属性
                    // 资源表名
                    String tablename = updatefile.substring(0, updatefile.indexOf("."));
                    // 资源属性名
                    String filename = updatefile.substring(updatefile.indexOf(".") + 1, updatefile.length());
                    // 资源键
                    Long id = JSON.parseObject(t).getLong(tablename);
                    // 获取资源
                    Object res = stateMachResourceService.getResource(tablename, id, true);
                    // 获取资源属性
                    Map<String, Object> rs = (Map<String, Object>) res;
                    updateFieldValue = rs.get(filename);
                } else if (updatefile.contains("=")) {// 如果value包含等号，直接赋与等号后面的值
                    updateFieldValue = updatefile.substring(1);
                } else {// 取task
                    updateFieldValue = JSON.parseObject(t).get(updatefile);
                }
                try{
                	 // 反射赋值
                    PropertyDescriptor prop = new PropertyDescriptor(updateFieldName, StateMachTaskBean.class);
                    Class<?> clazz = prop.getPropertyType();
                    String type = clazz.getName();
                    if (type.equals("java.lang.String")) {
                        prop.getWriteMethod().invoke(smt, updateFieldValue);
                    } else if (type.equals("java.util.Date")) {
                        // prop.getWriteMethod().invoke(smt, (Date)
                        // updateFieldValue);
                    } else if (type.equals("java.lang.Integer")) {
                        prop.getWriteMethod().invoke(smt, Integer.parseInt(updateFieldValue.toString()));
                    } else if (type.equals("int")) {
                        prop.getWriteMethod().invoke(smt, Integer.parseInt(updateFieldValue.toString()));
                    }
                }catch(Exception e){
                	throw new ServiceException(ResultStatus.SYS_ERROR.getCode());
                }
               
            }
        }
        return smt;
    }

    /**
     * 锁定解锁资源只支持已经添加好资源领用的情况
     *
     * @param lockType
     * @param taskId
     */
    @Override
    public void lockResource(String lockType, Long taskId) {
        if (lockType != null && !lockType.isEmpty()) {
            stateMachResourceService.lockResource(lockType.equals("lock") ? 1 : 0, taskId);
        }
    }

    /**
     * 根据ID获取task
     *
     * @param taskId
     * @return
     */
    @Override
    public StateMachTaskRetBean getTaskBeanById(String companyCode, Long taskId, boolean extData) {
        StateMachTaskRetBean retData = new StateMachTaskRetBean();
        // 存储当前状态对象
        PortalStateMachStateBean thisStateBean = null;
        // 根据taskId获取task主数据
        TaskBean taskBean = taskDao.getTaskById(companyCode, taskId);
        // 根据taskId获取关联数据
        Map<String, Object> ExtFormMap = new HashMap<String, Object>();// 表单扩展
        Map<String, Object> ExtResourceMap = new HashMap<String, Object>();// 资源扩展
        List<EntityInfoBean> EntityInfoBeans = new ArrayList<EntityInfoBean>();// 表单扩展Entity
        List<StateMachResourceTask> taskRels = stateMachResourceTaskService
                .getStateMachResourceTaskListByTaskId(taskId);
        for (StateMachResourceTask taskRel : taskRels) {

            // 获取括在对象实体定义(不一定用得上先注释)
            // EntityInfoBean en =
            // queryService.queryEntityInfo(taskRel.getRelObjectName());
            // String entityjson = JSON.toJSONString(en);

            // 获取扩展属性
            Map<String, Integer> sMap = new HashMap<String, Integer>();
            sMap.put("id", taskRel.getRelId().intValue());
            // Object extData =
            // crudV2Service.crudFindById(taskRel.getRelObjectName(), sMap);
            // stateMachResourceService.getResource("", 0L);
            if (taskRel.getRelType() == 1) {// 扩展资源
                Object extData1 = stateMachResourceService.getResource(taskRel.getRelObjectName(), taskRel.getRelId(),
                        extData);
                ExtResourceMap.put(taskRel.getRelObjectName(), extData1);
            } else if (taskRel.getRelType() == 2) {// 扩展表单
                Object extData2 = crudV2Service.crudFindById(taskRel.getRelObjectName(), sMap);
                
                Map<String, List<String>> map = portalStatemachFieldAuthService.
                		queryFieldAuthBy(taskBean.getConfId().intValue(), taskBean.getStateId().intValue(), taskRel.getRelObjectName());
    			List<String> invisibles = map.get("invisibles");//不可见字段
    			Map<String,Object> extDataObject = (Map<String,Object>)extData2;
    			for(String enk : invisibles){//设置不可见字段的值为null
    				if(extDataObject.containsKey(enk)){
    					extDataObject.put(enk, null);
    				}
    			}

                EntityInfoBeans.add(ChangeDisplayForStateMach(taskBean.getConfId(), taskBean.getStateId(),
                        taskRel.getRelObjectName()));

                ExtFormMap.put(taskRel.getRelObjectName(), extDataObject);
            }
        }
        // 获取当前状态扩展，如果括在没被包含，则插入
        // 获取当前状态的扩展
        thisStateBean = portalStateMachService.getCurrentState(taskBean.getConfId(), taskBean.getStateId());
        if (!StringUtils.isBlank(thisStateBean.getExtForm())) {
            EntityInfoBean willaddEIB = ChangeDisplayForStateMach(taskBean.getConfId(), thisStateBean.getId(),
                    thisStateBean.getExtForm());
            boolean hav = true;
            for (EntityInfoBean eib : EntityInfoBeans) {
                if (eib.getEntityName().equals(willaddEIB.getEntityName())) {
                    hav = false;
                }
            }
            if (hav) {
                EntityInfoBeans.add(willaddEIB);
            }
        }
        taskBean.setExtFormData(ExtFormMap);
        taskBean.setExtResourceData(ExtResourceMap);
        // StateExtData sed = new StateExtData();
        // 获取当前表单上的扩展数据
        if (extData) {
            StateExtData sed = portalStateMachService.GetStateExtDataByConfid(taskBean.getConfId(),
                    taskBean.getStateId());
            // 如果task上有资源业务类型，证明开始选了，优先task上的ResType
            if (taskBean.getResType() != null) {
                sed.setResType(taskBean.getResType().toString());
            }
            
            List<PortalCompanyRole> userHasRoleList = portalCompanyUserService
                    .api_queryUserHasRoleList(SpringWebUtils.getRequestUser(), SpringWebUtils.getRequestCompany());
            
            List<PortalStateMachHandleBean> handles = new ArrayList<PortalStateMachHandleBean>();
            Set<String> a = new HashSet<String>();
            if (sed.getHandles() != null) {
                for (PortalStateMachHandleBean h : sed.getHandles()) {
                    if (!a.contains(h.getControllerURL()) && 
                    		checkHandleAuthority(userHasRoleList,h.getExeRole(),h.getExeUser())) {
                        handles.add(h);
                        a.add(h.getControllerURL());
                    }
                }
            }
            sed.setHandles(handles);
            retData.setStateInfo(sed);
        }
        retData.setDataEntity(
                ChangeDisplayForStateMach(taskBean.getConfId(), taskBean.getStateId(), "portal_statemach_task"));// 主表单Entity
        retData.setData(taskBean);
        retData.setExtDataEntity(EntityInfoBeans);
        // 扩展数据给默认值，不然前端不知道是啥
        if (retData.getExtDataEntity() == null) {
            retData.setExtDataEntity(new ArrayList<EntityInfoBean>());
        }

        return retData;
    }
    
    private boolean checkHandleAuthority(List<PortalCompanyRole> userHasRoleList,String exeRole,String exeUser){
    	String currenUser = SpringWebUtils.getRequestUser();
    	boolean result = false;
    	if(checkExeRole(userHasRoleList,exeRole) && checkExeUser(currenUser,exeUser)){
    		result = true;
    	}
    	return result;
    }
    
    private boolean checkExeRole(List<PortalCompanyRole> userHasRoleList,String exeRole){
    	if(StringUtil.isNullOrBlank(exeRole)){
    		return true;
    	}
    	for (PortalCompanyRole cr : userHasRoleList) {
            if (cr.getPortalCompanyRoleId().toString().equals(exeRole)) {
               return true;
            }
        }
    	return false;
    }
    
    private boolean checkExeUser(String currentUser,String exeUser){
    	if(StringUtil.isNullOrBlank(exeUser)){
    		return true;
    	}
    	if(currentUser.equals(exeUser)){
    		return true;
    	}
    	return false;
    }

    /**
     * 根据confID获取task结构
     *
     * @param companyCode
     * @param confId
     * @return
     */
    public StateMachTaskRetBean getTaskBeanByConfId(String companyCode, Long confId) {
        StateMachTaskRetBean retData = new StateMachTaskRetBean();
        // 存储当前状态对象
        PortalStateMachStateBean thisStateBean = null;
        // 获取初始化状态
        thisStateBean = portalStateMachService.getInitState(confId);
        if (thisStateBean != null) {
            retData.setDataEntity(ChangeDisplayForStateMach(confId, thisStateBean.getId(), "portal_statemach_task"));// 主表单Entity
            if (!StringUtils.isBlank(thisStateBean.getExtForm())) {
                List<EntityInfoBean> EntityInfoBeans = new ArrayList<EntityInfoBean>();// 表单扩展Entity
                EntityInfoBeans
                        .add(ChangeDisplayForStateMach(confId, thisStateBean.getId(), thisStateBean.getExtForm()));
                retData.setExtDataEntity(EntityInfoBeans);
            }
            StateExtData sed = portalStateMachService.GetStateExtDataByConfid(confId, thisStateBean.getId());
            // 扩展数据给默认值，不然前端不知道是啥
            if (retData.getExtDataEntity() == null) {
                retData.setExtDataEntity(new ArrayList<EntityInfoBean>());
            }
            
            List<PortalCompanyRole> userHasRoleList = portalCompanyUserService
                    .api_queryUserHasRoleList(SpringWebUtils.getRequestUser(), SpringWebUtils.getRequestCompany());
            
            // 过滤重复的按钮
            List<PortalStateMachHandleBean> handles = new ArrayList<PortalStateMachHandleBean>();
            Set<String> a = new HashSet<String>();
            for (PortalStateMachHandleBean h : sed.getHandles()) {
            	 if (!a.contains(h.getControllerURL()) && checkExeRole(userHasRoleList,h.getExeRole()) 
                 		&& checkExeUser(SpringWebUtils.getRequestUser(),h.getExeUser())) {
                    handles.add(h);
                    a.add(h.getControllerURL());
                }
            }
            sed.setHandles(handles);
            retData.setStateInfo(sed);
        }
        return retData;
    }

    /**
     * 获取流程状态下自定义的entity显示配置
     *
     * @param confId
     * @param stateId
     * @param entityName
     * @return
     */
    private EntityInfoBean ChangeDisplayForStateMach(Long confId, Long stateId, String entityName) {
        // 获取原有entity配置
        EntityInfoBean ret = queryService.queryEntityInfo(entityName);
        // 获取在状态机上的entity display配置
        List<PortalStateMachField> changeField = portalStateMachService.getFieldForStateMach(confId, stateId,
                entityName);

        //根据当前用户获取节点上设置的不可用以及不可见的属性
        Map<String, List<String>> map = null;
        if(confId!=null && stateId!=null){
        	map = portalStatemachFieldAuthService.queryFieldAuthBy(confId.intValue(), stateId.intValue(), entityName);
        }
        List<String> invisibles = map!=null?map.get("invisibles"):null;
        List<String> non_editables = map!=null?map.get("non_editables"):null;
        List<String> required = map!=null?map.get("required"):null;
        // 用状态机上的display替换原有的（非空才替换）
        if (ret != null && changeField != null && changeField.size() > 0) {
            for (int j = 0; j < changeField.size(); j++) {
                if (!StringUtils.isBlank(changeField.get(j).getDisplay())) {
                    for (int i = 0; i < ret.getAttrs().size(); i++) {
                        if (ret.getAttrs().get(i).getField().getPhysicalField()
                                .equals(changeField.get(j).getFieldName())) {


                            JSONObject oldjson = JSON.parseObject(ret.getAttrs().get(i).getDisplay());
                            JSONObject newjson = JSON.parseObject(changeField.get(j).getDisplay());
                            if (oldjson != null) {
                                if (newjson != null) {
                                    for (String key : newjson.keySet()) {
                                        oldjson.put(key, newjson.get(key));
                                    }
                                }
                                
                                ret.getAttrs().get(i).setDisplay(oldjson.toJSONString());
                            } else {
                            	JSONObject ojson = null;
                            	if(changeField.get(j).getDisplay()!=null){
                            		 ojson = JSON.parseObject(changeField.get(j).getDisplay());
                            	}else{
                            		ojson = new JSONObject();
                            	}
								
                                ret.getAttrs().get(i).setDisplay(ojson.toJSONString());// 老方案完全替换
                            }
                        }
                    }
                }
            }
        }
        if(ret!=null && ret.getAttrs()!=null){
        	for(EntityFieldInfoBean f : ret.getAttrs()){
        		JSONObject ojson = (StringUtil.isNotBlank(f.getDisplay()))?JSONObject.parseObject(f.getDisplay()):new JSONObject();
        		if(invisibles!=null && invisibles.contains(f.getField().getFieldName())){
        			ojson.put("active", false);
        		}
        		if(non_editables!=null && non_editables.contains(f.getField().getFieldName())){
        			ojson.put("disabled", true);
    			}
    			if(required!=null && required.contains(f.getField().getFieldName())){
    				ojson.put("required", true);
    			}
    			f.setDisplay(ojson.toJSONString());
        	}
        }
    	
        
        return ret;
    }

    /**
     * 根据流程配置更新扩展表单属性
     *
     * @param inparas
     * @param changeStateId
     * @param t
     * @param confId
     * @return
     * @throws ScriptException
     */
    private Map<String, Object> updateExtDataForState(Map<String, Object> inparas, Long changeStateId, String t,
                                                      Long confId,String tableName){
        PortalStateMachStateBean changeStateBean = portalStateMachService.getCurrentState(confId, changeStateId);
        if (!StringUtils.isBlank(changeStateBean.getUpdateField())) {
            JSONArray jarr = JSONArray.parseArray(changeStateBean.getUpdateField());
            for (Iterator<Object> iterator = jarr.iterator(); iterator.hasNext(); ) {
                JSONObject exp = (JSONObject) iterator.next();
                // 如果包含table属性，且table的值等于当前状态扩展表单的值
                if (exp.containsKey("table") && exp.getString("table").equals(tableName)) {
                    String updatefile = "";
                    // 更新字段
                    String updateFieldName = exp.getString("key");
                    Object updateFieldValue = null;
                    // 解析更新内容
                    if (exp.getString("value") == null || exp.getString("value").isEmpty()) {// 解析js
                        // 创建js处理对象
                        ScriptEngineManager manager = new ScriptEngineManager();
                        ScriptEngine engine = manager.getEngineByName("JavaScript");
                        // 获取js
                        JSONObject js = exp.getJSONObject("js");
                        // 获取参数
                        JSONArray paras = JSONArray.parseArray(js.getString("para"));
                        for (Iterator<Object> parasiterator = paras.iterator(); parasiterator.hasNext(); ) {
                            JSONObject para = (JSONObject) parasiterator.next();
                            JSONObject valjson = JSON.parseObject(t);
                            // 处理para参数结构
                            String[] strparas = (para.getString("value")).split("\\.");
                            int i = 0;
                            for (String val : strparas) {
                                i++;
                                if (i < strparas.length) {
                                    valjson = valjson.getJSONObject(val);
                                }
                            }
                            engine.put(para.getString("key"), valjson.getString(strparas[strparas.length - 1]));
                        }
                        // String a = "{\"js\":\"IF(isdriver==1)\'taskUser\'
                        // ELSE\'fms_driver.username\'\"}";
                        // JSONObject aj = JSON.parseObject(a);
                        // System.out.printf(js.getString("js"));
                        try {
							updatefile = (String) engine.eval(js.getString("js"));
						} catch (ScriptException e) {
							throw new ServiceException(ResultStatus.SYS_ERROR.getCode(),"执行javascript脚本失败");
						}
                        // updatefile = (String)
                        // engine.eval("if(isdriver==1){'taskUser'}
                        // else{'fms_driver.username'}");
                    } else {// 解析value
                        updatefile = exp.getString("value");
                    }
                    if (updatefile.contains(".")) {// 如果value包含'.'表示源资源内属性
                        // 资源表名
                        String tablename = updatefile.substring(0, updatefile.indexOf("."));
                        // 资源属性名
                        String filename = updatefile.substring(updatefile.indexOf(".") + 1, updatefile.length());
                        // 资源键
                        Long id = JSON.parseObject(t).getLong(tablename);
                        // 获取资源
                        Object res = stateMachResourceService.getResource(tablename, id, true);
                        // 获取资源属性
                        Map<String, Object> rs = (Map<String, Object>) res;
                        updateFieldValue = rs.get(filename);
                    } else if (updatefile.contains("=")) {// 如果value包含等号，直接赋与等号后面的值
                        updateFieldValue = updatefile.substring(1);
                    } else {// 取task
                        updateFieldValue = JSON.parseObject(t).get(updatefile);
                    }
                    inparas.put(updateFieldName, updateFieldValue);
                }
            }
        }
        return inparas;
    }

    public void test(String a) {
        stateMachService.setConfId(1l);
        stateMachService.setTaskId(0l);
        stateMachService.addListener(this, "test2", "a");
        // stateMachService.execute(a);
    }

    public void test2(String a) {
        String b = a;
        String c = b;
    }

    @Override
    public List<TaskBean> getTaskbyRelId(Long relId, String relType) {
        return taskDao.getTaskbyRelId(relId, relType, SpringWebUtils.getRequestCompany(),
                SpringWebUtils.getRequestUser());
    }

    /*
     * 添加历史记录
     */
    private void insertTaskHistory(Long taskId, Long StateId, Long HandleId, Long confId, Long ChangeState,
                                   String remarks) {
        StateMachTaskHistory taskHistory = new StateMachTaskHistory();
        taskHistory.setTaskId(taskId);
        taskHistory.setCompanyCode(SpringWebUtils.getRequestCompany());
        taskHistory.setUserName(SpringWebUtils.getRequestUser());
        taskHistory.setStateId(StateId);
        taskHistory.setHandleId(HandleId);
        taskHistory.setTaskHistoryTime(new Date());
        taskHistory.setConfId(confId);
        taskHistory.setChangeState(ChangeState);
        taskHistory.setRemarks(remarks);
        portalStateMachTaskHistoryService.insertTaskHistory(taskHistory);
    }

}
